﻿namespace Trader.Indicators.TechnicalAnalysis
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using BO.Interface;
    using Interface;

    public class WebHitsSignal : ISignal
    {
        #region Private Member's

        ///<summary>
        ///Number of days to check before the buy date</summary>
        private readonly int days;

        public int TestDays
        {
            get { return days; }
        }

        public Guid ID
        {
            get { return new Guid("AB908860-3C2A-446a-AD56-DF1E74A24BE8"); }
        }

        public string Name
        {
            get { return string.Format("WebHits ({0})", days); }
        }

        public Uri URL
        {
            get { return new Uri("http://www.google.com"); }
        }

        #endregion

        #region Cons'

        ///<summary>
        ///WebHitsSignal constructor: calculates the days and deviation</summary>
        public WebHitsSignal(int days)
        {
            this.days = days;
        }

        #endregion

        #region ISignal Members

        ///<summary>
        ///Generate a recomendation for the stock at the spesific time
        ///</summary>
        ///<param name="stock"> The stock to buy</param>
        ///<param name="buyTime"> The date for buying</param>
        ///<returns>Yes or No</returns>
        public Recommendation GenerateRecommendation(IStock stock, DateTime buyTime)
        {
            if (!stock.Quotes.ContainsKey(buyTime)) //Check if buy point has quote
            {
                return Recommendation.NONE;
            }

            IList<decimal> volumes = GetVolumes(stock, buyTime);

            IEnumerable<decimal> closingPrices = GetPeriodClosings(stock, buyTime);
            if (!closingPrices.Any()) //No quotes during period
            {
                return Recommendation.NONE;
            }

            var webHits = stock.GetSearchResults(buyTime);

            if (webHits == null) return Recommendation.NONE;

            DateTime date = buyTime;
            date -= TimeSpan.FromDays(7);

            int numOfValues = closingPrices.Count();

            

            // If the web hits increses at least in 300%
            if (webHits > (3 * stock.GetSearchResults(date)))
            {
                if (stock.Quotes[buyTime].Closing  > (1.1m * closingPrices.Average()) &&
                    stock.Quotes[buyTime].Volume > (1.2m * volumes.Average()))
                {
                    return Recommendation.BUY;
                }
                if ((stock.Quotes[buyTime].Closing * 1.1m) < closingPrices.Average() &&
                    stock.Quotes[buyTime].Volume > (1.2m * volumes.Average()))
                {
                    return Recommendation.SHORT;
                }
            }

            return Recommendation.NONE;
        }

        #endregion

        ///<summary>
        ///Get Period Closings
        ///</summary>
        ///<param name="stock"> The stock to buy</param>
        ///<param name="buyTime"> The date for buying</param>
        ///<returns></returns>
        private IEnumerable<decimal> GetPeriodClosings(IStock stock, DateTime buyTime)
        {
            var periodClosings = new List<decimal>();
            for (DateTime dateIterator = buyTime - TimeSpan.FromDays(days + 1);
                 dateIterator < buyTime;
                 dateIterator += TimeSpan.FromDays(1))
            {
                IQuote quote;
                if (stock.Quotes.TryGetValue(dateIterator, out quote))
                {
                    periodClosings.Add(quote.Closing);
                }
            }
            return periodClosings;
        }

        ///<summary>
        ///Get all stock trade volumes from the time before the buy date
        ///</summary>
        ///<param name="stock"> The stock</param>
        ///<param name="buyTime"> The buy date</param>
        ///<returns> List of trade volumes</returns>
        private IList<decimal> GetVolumes(IStock stock, DateTime buyTime)
        {
            var volume = new List<decimal>();
            for (DateTime dateIterator = buyTime - TimeSpan.FromDays(days + 1);
                 dateIterator < buyTime;
                 dateIterator += TimeSpan.FromDays(1))
            {
                IQuote quote;
                if (stock.Quotes.TryGetValue(dateIterator, out quote))
                {
                    volume.Add(quote.Volume);
                }
            }
            return volume;
        }

        public override string ToString()
        {
            return string.Format("WebHits({0})", days);
        }
    }
}